package com.seeyon.apps.commonExt.util;

import com.seeyon.apps.commonExt.domain.AbortProcessExt;
import com.seeyon.apps.commonExt.domain.StartProcessExt;
import com.seeyon.apps.util.CAP4FormKit;
import com.seeyon.apps.util.CommonUtilExt;
import com.seeyon.cap4.form.bean.*;
import com.seeyon.cap4.form.modules.engin.base.formData.CAP4FormDataManager;
import com.seeyon.cap4.form.modules.engin.base.formData.CAP4SessionFormDataManager;
import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.affair.manager.AffairManager;
import com.seeyon.ctp.common.authenticate.domain.User;
import com.seeyon.ctp.common.exceptions.BusinessException;
import com.seeyon.ctp.common.po.affair.CtpAffair;
import com.seeyon.ctp.organization.bo.V3xOrgMember;
import com.seeyon.ctp.organization.manager.OrgManager;
import com.seeyon.ctp.rest.resources.SeeyonBPMAppHandler;
import com.seeyon.ctp.rest.resources.SeeyonBPMManager;
import com.seeyon.ctp.util.Strings;
import com.seeyon.ctp.util.json.JSONUtil;
import com.seeyon.ctp.workflow.bean.params.SeeyonBPMHandParam;
import com.seeyon.ctp.workflow.bean.params.SeeyonBPMHandParam4Start;
import com.seeyon.ctp.workflow.service.api.InstApiService;
import com.seeyon.ctp.workflow.vo.SeeyonBPMHandResult;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.map.MapUtil;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @description:
 * @author: huangjin
 * @time: 2025/3/21 10:12
 */
public class BpmnManagerExt {

    private static final Logger logger = LoggerFactory.getLogger(BpmnManagerExt.class);

    /**
     * 启动流程
     * @description:
     * @author: huangjin
     * @time: 2025/3/31 09:47
     * @param params
     * @return
     * @throws BusinessException
     */
    public static SeeyonBPMHandResult startProcess(Map<String, Object> params) throws BusinessException {
        User currentUser = AppContext.getCurrentUser();
        Assert.notNull(currentUser, "请传入申请人信息！");
        String checkRet = checkNecessaryParams(params, "appName");
        Assert.isTrue(StringUtils.isBlank(checkRet), checkRet);
        SeeyonBPMHandParam4Start startParam = new SeeyonBPMHandParam4Start();
        initParam(params, startParam);
        String templateCode = startParam.getStringParam("templateCode");
        Assert.notBlank(templateCode, "No parameter or the value is NULL :templateCode");
        InstApiService instApiService = (InstApiService) AppContext.getBean("instApiService");
        return instApiService.transStartProcess(startParam);
    }

    public static SeeyonBPMHandResult startProcess(StartProcessExt params) throws BusinessException {
        Map<String, Object> para = CommonUtilExt.convertToMapRecursive(params);
        return startProcess(para);
    }


    /**
     * 终止流程
     * @description:
     * @author: huangjin
     * @time: 2025/3/31 13:22
     * @param param
     * @throws BusinessException
     */
    public static void abortProcess(AbortProcessExt param) throws BusinessException {
        CtpAffair affair = getAffair(param.getSummaryId());
        Map<String, Object> params = new HashMap<>();
        params.put("appName", param.getAppName());
        params.put("workitemId", affair.getSubObjectId().toString());
        Map<String, Object> data = new HashMap<>();
        params.put("data", data);
        data.put("stopOpinion", param.getStopOpinion());
        SeeyonBPMAppHandler handler = SeeyonBPMManager.getBPMHandler(param.getAppName());
        handler.transStepStop(params);
    }

    public static CtpAffair getAffair(Long summaryId) throws BusinessException {
        CtpAffair ctpAffair = null;
        AffairManager affairManager = (AffairManager) AppContext.getBean("affairManager");
        List<CtpAffair> pendingAffairs = affairManager.getPendingAffairs(summaryId);
        if (Strings.isNotEmpty(pendingAffairs)) {
            ctpAffair = pendingAffairs.get(0);
        }
        return ctpAffair;
    }

    private static String checkNecessaryParams(Map<String, Object> params, String... keys) {
        String ret = null;
        StringBuilder missKey = new StringBuilder();
        if (keys != null && keys.length != 0) {
            if (params != null) {
                for(String key : keys) {
                    if (!params.containsKey(key) || params.get(key) == null || params.get(key) instanceof String && Strings.isBlank(params.get(key).toString())) {
                        missKey.append(key).append(",");
                    }
                }
            }

            if (missKey.length() > 0) {
                ret = "No parameter or the value is NULL :" + missKey.toString();
            }

            return ret;
        } else {
            return ret;
        }
    }

    private static void initParam(Map<String, Object> reqDatas, SeeyonBPMHandParam param) {
        if (reqDatas != null && param != null) {
            param.setAppName((String)reqDatas.get("appName"));
            User user = AppContext.getCurrentUser();
            OrgManager orgManager = (OrgManager) AppContext.getBean("orgManager");
            try {
                V3xOrgMember member =orgManager.getMemberById(user.getId());
                param.setCurrentUser(member);
            } catch (BusinessException e) {
                logger.error("rest接口初始化人员信息失败", e);
            }

            param.setAppData((Map)reqDatas.get("data"));
        }
    }

    public String getMasterFieldValue(SeeyonBPMHandResult seeyonBPMHandResult, FormBean formBean, String display) throws BusinessException, SQLException {
        Object appBussinessDataObj = seeyonBPMHandResult.getResultData("app_bussiness_data");
        if (null == appBussinessDataObj) {
            return null;
        }
        Map<String, Object> resultMap = JSONUtil.parseJSONString(appBussinessDataObj.toString(), new TypeReference<Map<String, Object>>() {}.getType());
        if (MapUtil.isEmpty(resultMap)) {
            return null;
        }
        long affairId = MapUtil.getLong(resultMap, "affairId");
        AffairManager affairManager = (AffairManager) AppContext.getBean("affairManager");
        CtpAffair ctpAffair = affairManager.get(affairId);
        Long formRecordid = ctpAffair.getFormRecordid();
        CAP4FormDataManager cap4FormDataManager = (CAP4FormDataManager) AppContext.getBean("cap4FormDataManager");
        List<FormDataMasterBean> formDataMasterBeans = cap4FormDataManager.selectMasterDataById(new Long[]{formRecordid}, formBean, null);
        return CAP4FormKit.getFieldValue(formDataMasterBeans.get(0), display, String.class);
    }

    public void addSub(FormDataMasterBean masterDataBean, FormTableBean formTableBean, Map<String, Object> dtlParams) {
        Map<String, Object> params = new HashMap<>();
        List<FormDataSubBean> subData = masterDataBean.getSubData(formTableBean.getTableName());
        for (Map.Entry<String, Object> entry : dtlParams.entrySet()) {
            FormFieldBean formFieldBean = formTableBean.getFieldBeanByDisplay(entry.getKey());
            if (null == formFieldBean && !entry.getKey().equals("id")) {
                continue;
            }
            if (null == formFieldBean) {
                params.put("id", entry.getValue());
                continue;
            }
            params.put(formFieldBean.getName(), entry.getValue());
        }
        if (MapUtil.isEmpty(params)) {
            return;
        }
        for (FormDataSubBean subDatum : subData) {
            if(subDatum.getId().equals(params.get("id"))) {
                subDatum.addFieldValue(params, null);
                return;
            }
        }
        FormDataSubBean formDataSubBean = new FormDataSubBean(params, formTableBean, masterDataBean, new boolean[]{false});
        subData.add(formDataSubBean);
    }

    public void setCache(FormDataMasterBean master) {
        Assert.notNull(AppContext.getCurrentUser(), "当前用户为空!");
        CAP4SessionFormDataManager cap4SessionFormDataManager = (CAP4SessionFormDataManager) AppContext.getBean("cap4SessionFormDataManager");
        cap4SessionFormDataManager.put2Cache(master, AppContext.currentUserId());
    }
}
